package com.woniu.crowd.service.impl;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniu.crowd.common.CrowdException;
import com.woniu.crowd.infra.config.AlipayConfig;
import com.woniu.crowd.infra.model.CrowdOrder;
import com.woniu.crowd.infra.mapper.CrowdOrderMapper;
import com.woniu.crowd.infra.model.CrowdOrderLog;
import com.woniu.crowd.infra.model.CrowdUserRele;
import com.woniu.crowd.infra.model.CrowdfundingProducts;
import com.woniu.crowd.service.CrowdOrderLogService;
import com.woniu.crowd.service.CrowdOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.crowd.service.CrowdUserReleService;
import com.woniu.crowd.service.CrowdfundingProductsService;
import com.woniu.crowd.service.dto.CrowdOrderDto;
import com.woniu.crowd.service.dto.CrowdfundingProductsDto;
import com.woniu.crowd.service.form.CreatCrowdOrderForm;
import com.woniu.crowd.service.form.PartakeCrowdForm;
import com.woniu.exception.LXLGException;
import com.woniu.product.client.ProductQueryClient;
import com.woniu.product.client.result.SpuResultInfo;
import com.woniu.result.Result;
import com.woniu.user.client.AddressQueryClient;
import com.woniu.user.client.UserInfoClient;
import com.woniu.user.client.result.AddressResultInfo;
import com.woniu.user.client.result.UserResultInfo;
import com.woniu.util.DateUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * <p>
 * 众筹订单表 服务实现类
 * </p>
 *
 * @author Lucas
 * @since 2022-11-26
 */
@Service
public class CrowdOrderServiceImpl extends ServiceImpl<CrowdOrderMapper, CrowdOrder> implements CrowdOrderService {
    @Resource
    private UserInfoClient userInfoClient;
    @Resource
    private ProductQueryClient productQueryClient;
    @Resource
    private CrowdUserReleService crowdUserReleService;
    @Resource
    private CrowdfundingProductsService crowdfundingProductsService;
    @Resource
    private CrowdOrderLogService crowdOrderLogService;
    @Resource
    private AddressQueryClient addressQueryClient;
    @Resource
    private Snowflake snowflake;

    @Override
    public CrowdOrder createCrowdOrder(CreatCrowdOrderForm creatCrowdOrderForm) {
        CrowdOrder crowdOrder = BeanUtil.copyProperties(creatCrowdOrderForm, CrowdOrder.class);
        crowdOrder.setCrowdOrderNum("crowd" + snowflake.nextId());
        //查询用户信息
        UserResultInfo data = userInfoClient.searchUserInfo(creatCrowdOrderForm.getCrowdUserId()).getData();
        if (data == null) throw new LXLGException(CrowdException.CROWD_USER_NON_EXISTENT);
        crowdOrder.setCrowdOrderUser(data.getUserNickname());

        //查询用户地址信息
        AddressResultInfo addressResultInfo = addressQueryClient.getUserAddressById(creatCrowdOrderForm.getCrowdAddressId()).getData();
        if (addressResultInfo == null) throw new LXLGException(CrowdException.CROWD_ADDRESS_NON_EXISTENT);
        crowdOrder.setCrowdOrderAddress(addressResultInfo.getAddressInfo());

        crowdOrder.setCrowdOrderState(crowdOrder.getCrowdOrderState());

        save(crowdOrder);

        CrowdOrderLog crowdOrderLog = new CrowdOrderLog();
        crowdOrderLog.setCrowdLogTime(DateUtil.parseDateLong());
        crowdOrderLog.setCrowdUserId(creatCrowdOrderForm.getCrowdUserId());
        crowdOrderLog.setCrowdOrderId(crowdOrder.getCrowdOrderId());
        crowdOrderLog.setCrowdOrderNum(crowdOrder.getCrowdOrderNum());
        crowdOrderLog.setCrowdOrderContent(creatCrowdOrderForm.getCrowdOrderContent());
        crowdOrderLogService.save(crowdOrderLog);
        return crowdOrder;
    }


    @Override
    public CrowdOrderDto userPartakeCrowd(PartakeCrowdForm partakeCrowdForm) throws UnsupportedEncodingException, AlipayApiException {
        CrowdfundingProducts byId = crowdfundingProductsService.getById(partakeCrowdForm.getCrowdId());
        if (byId == null) throw new LXLGException(CrowdException.CROWD_NON_EXISTENT);
        Long startTime = DateUtil.parseDateString(byId.getStartDate(), "yyyy-MM-dd HH:mm:ss");
        Long endTime = DateUtil.parseDateString(byId.getEndDate(), "yyyy-MM-dd HH:mm:ss");
        Long now = DateUtil.parseDateString(DateUtil.parseDateLong(), "yyyy-MM-dd HH:mm:ss");
        if (now < startTime || now > endTime) throw new LXLGException(CrowdException.CROWD_EXPIRED);
        if (byId.getTotalAmount().compareTo(byId.getTargetAmount()) >= 0)
            throw new LXLGException(CrowdException.CROWD_GOAL_ACHIEVED);


        CrowdUserRele crowdUserRele = new CrowdUserRele();
        crowdUserRele.setUserId(partakeCrowdForm.getUserId());
        crowdUserRele.setCrowd(partakeCrowdForm.getCrowdId());
        crowdUserRele.setAddressId(partakeCrowdForm.getAddressId());
        crowdUserRele.setPartakeTime(DateUtil.parseDateLong());
        crowdUserRele.setCrowdReceiverUser(partakeCrowdForm.getCrowdReceiverUser());
        crowdUserRele.setCrowdReceiverPhone(partakeCrowdForm.getCrowdReceiverPhone());
        crowdUserReleService.save(crowdUserRele);


        Result<SpuResultInfo> spuInfoBySpuId = productQueryClient.getSpuInfoBySpuId(partakeCrowdForm.getProductId(),-1);

        SpuResultInfo spuResultInfo = spuInfoBySpuId.getData();

        System.out.println("spuResultInfo:" + spuResultInfo);


        CrowdOrder crowdOrder = new CrowdOrder();
        crowdOrder.setCrowdOrderNum("ZC" + snowflake.nextId());
        crowdOrder.setCrowdId(byId.getId());
        //查询用户信息
        UserResultInfo data = userInfoClient.searchUserInfo(partakeCrowdForm.getUserId()).getData();
        if (data == null) throw new LXLGException(CrowdException.CROWD_USER_NON_EXISTENT);

        //查询用户地址信息
        AddressResultInfo addressResultInfo = addressQueryClient.getUserAddressById(partakeCrowdForm.getAddressId()).getData();
        if (addressResultInfo == null) throw new LXLGException(CrowdException.CROWD_ADDRESS_NON_EXISTENT);

        crowdOrder.setCrowdOrderUser(data.getUserNickname());
        crowdOrder.setCrowdUserId(partakeCrowdForm.getUserId());
        crowdOrder.setCrowdOrderAddress(addressResultInfo.getAddressInfo());
        crowdOrder.setCrowdAddressId(partakeCrowdForm.getAddressId());
        crowdOrder.setCrowdReceiverUser(partakeCrowdForm.getCrowdReceiverUser());
        crowdOrder.setCrowdReceiverPhone(partakeCrowdForm.getCrowdReceiverPhone());
        crowdOrder.setCrowdOrderCreatetime(DateUtil.parseDateLong());
        crowdOrder.setCrowdOrderPrice(spuResultInfo.getMinPrice());
        crowdOrder.setCrowdOrderState("CREATE");
        save(crowdOrder);

        CrowdOrderLog crowdOrderLog = new CrowdOrderLog();
        crowdOrderLog.setCrowdLogTime(DateUtil.parseDateLong());
        crowdOrderLog.setCrowdUserId(partakeCrowdForm.getUserId());
        crowdOrderLog.setCrowdOrderId(crowdOrder.getCrowdOrderId());
        crowdOrderLog.setCrowdOrderNum(crowdOrder.getCrowdOrderNum());
        crowdOrderLog.setCrowdOrderContent("创建众筹订单");
        crowdOrderLogService.save(crowdOrderLog);

        return BeanUtil.copyProperties(crowdOrder, CrowdOrderDto.class);
    }

    @Override
    public String crowdPay(String crowdOrderNum) throws Exception {
        CrowdOrder crowdOrder = getOne(new QueryWrapper<CrowdOrder>().eq("crowd_order_num", crowdOrderNum));
        //todo 支付
        //查询订单状态
        if (crowdOrder != null && crowdOrder.getCrowdOrderState().equals("CREATE")) {
            //获得初始化的AlipayClient
            AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

            //设置请求参数
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            alipayRequest.setReturnUrl(AlipayConfig.return_url);
            alipayRequest.setNotifyUrl(AlipayConfig.notify_url);


            //商户订单号，商户网站订单系统中唯一订单号，必填
            String out_trade_no = new String(crowdOrderNum.getBytes("ISO-8859-1"), "UTF-8");
            //付款金额，必填
            String total_amount = new String(crowdOrder.getCrowdOrderPrice().toString().getBytes("ISO-8859-1"), "UTF-8");
            //订单名称，必填
            String subject = "支付菜品订单";
            //商品描述，可空
            String body = "菜品订单";

            alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                    + "\"total_amount\":\"" + total_amount + "\","
                    + "\"subject\":\"" + subject + "\","
                    + "\"body\":\"" + body + "\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

            //请求
            String result = alipayClient.pageExecute(alipayRequest).getBody();
            return result;
        }
        return null;
    }

    @Override
    public void setPayOk(String message) {
        CrowdOrder crowdOrder = getOne(new QueryWrapper<CrowdOrder>().eq("crowd_order_num", message));
        crowdOrder.setCrowdOrderState("PAID");
        updateById(crowdOrder);

        CrowdfundingProducts byId = crowdfundingProductsService.getById(crowdOrder.getCrowdId());
        if (byId == null) throw new LXLGException(CrowdException.CROWD_NON_EXISTENT);


        Result<SpuResultInfo> spuInfoBySpuId = productQueryClient.getSpuInfoBySpuId(byId.getProductId(),-1);

        SpuResultInfo spuResultInfo = spuInfoBySpuId.getData();

        System.out.println("spuResultInfo:" + spuResultInfo);

        byId.setTotalAmount(byId.getTotalAmount().add(spuResultInfo.getMinPrice()));
        byId.setUserCount(byId.getUserCount() + 1);
        crowdfundingProductsService.updateById(byId);

        CrowdOrderLog crowdOrderLog = new CrowdOrderLog();
        crowdOrderLog.setCrowdLogTime(DateUtil.parseDateLong());
        crowdOrderLog.setCrowdUserId(crowdOrder.getCrowdUserId());
        crowdOrderLog.setCrowdOrderId(crowdOrder.getCrowdOrderId());
        crowdOrderLog.setCrowdOrderNum(message);
        crowdOrderLog.setCrowdOrderContent("众筹支付成功");

        crowdOrderLogService.save(crowdOrderLog);
    }
}
